#ifndef MATERIAL_H
#define MATERIAL_H
#include <vector>
#include "globals.h"
#include "shader.h"
#include "color.h"
#include "bsdf.h"
#include "intersection.h"
#include "configurable.h"
namespace gemren
{
	class material : public configurable
	{
	public:
		virtual ~material(){}
		static material_ptr default_material();
		material(): inverted_normals(false){}
		virtual void shade(random* ran, const scene* sc, intersection* i) = 0;
		virtual void direct_lighting(random* ran, const scene* sc, intersection* i) = 0;
		
		virtual void bounce(random* ran, const scene* sc, intersection* i) = 0;
		virtual void interact(random* ran, const scene* sc, intersection* i);
		virtual void bounce_fast(random* ran, const scene* sc, intersection* i) = 0;
		virtual void interact_fast(random* ran, const scene* sc, intersection* i);
		
		virtual bool is_directly_lighted() {return false;}
		virtual bool is_light_transmitting(){return false;}
		virtual bool is_light_emitting(){return false;}
		virtual color_s throughput(const coord& incoming, const coord& outcoming, const coord& normal) const=0;
		static material* create_material(const char definition_file[]);
		virtual void announce_properties(const std::string& prefix, property_announcer announcer)
		{
			announcer((prefix+".inverted_normals").c_str(), ANNOUNCED_BOOL, bool_to_str(inverted_normals).c_str());
		}
		virtual float pdf(const coord& incoming, const coord& outcoming, const coord& normal) const{ return 0.0f; }
	protected:
		virtual err_t set_my_bool(std::string& name, const bool value)
		{
			if(name=="inverted_normals")
			{
				inverted_normals = value;
				return ERR_OK;
			}
			else
				return ERR_BAD_PROP;
		}
		bool inverted_normals;
	};
	
	class bsdf_material : public material
	{
	public:
		bsdf_material(): BSDF(new brdf_diffuse), surface_shader(0), color(1.0f), display_color(1.0f){}
		virtual ~bsdf_material() { delete BSDF; delete surface_shader; }
		virtual void interact(random* ran, const scene* sc, intersection* i);
		virtual void bounce_fast(random* ran, const scene* sc, intersection* i);
		virtual void interact_fast(random* ran, const scene* sc, intersection* i);
		
		virtual void shade(random* ran, const scene* sc, intersection* i);
		virtual void direct_lighting(random* ran, const scene* sc, intersection* i);
		virtual void bounce(random* ran, const scene* sc, intersection* i);
		virtual color_s throughput(const coord& incoming, const coord& outcoming, const coord& normal)const{ return BSDF->throughput(incoming, outcoming, normal); }
		friend class material;
		friend class brdf_diffuse;
		friend class btdf_fresnel;
		
		virtual bool is_directly_lighted() {return BSDF->is_directly_lighted();}
		virtual bool is_light_transmitting(){return BSDF->is_light_transmitting();}

		virtual void announce_properties(const std::string& prefix, property_announcer announcer);
		virtual err_t set_int(std::string& name, const int value);
		virtual err_t set_string(std::string& name, const std::string& value);
		virtual err_t set_float(std::string& name, const float value);
		virtual err_t set_bool(std::string& name, const bool value);
		virtual float pdf(const coord& incoming, const coord& outcoming, const coord& normal)const{ return BSDF->pdf(incoming, outcoming, normal); }
	protected:
		shader* surface_shader;
		color_s color;
		spectrum_dynamic display_color;
		bsdf* BSDF;
	protected:
	};


}
#endif
